package fem2.material.cohesive_law2;

import fem2.Element;
import fem2.element.crack_sda2.SDAElement;
import inf.jlinalg.Array2DMatrix;
import inf.jlinalg.ArrayVector;
import inf.jlinalg.IMatrix;
import inf.jlinalg.IVector;

/**
 * cohesive law for pure Mode 1 opening with linear law for crack propagation
 * tracking
 * 
 * @author hbui
 * 
 */
public class ExponentialCohesiveLaw extends CohesiveLaw {

	private double ef;
	private double km1;
	private double km2;

	public ExponentialCohesiveLaw(double Gf, double ft, double km) {
		super(Gf, ft);
		this.ef = Gf / ft;
		this.km1 = km;
		this.km2 = km;
	}

	public ExponentialCohesiveLaw(double Gf, double ft, double km1, double km2) {
		super(Gf, ft);
		this.ef = Gf / ft;
		this.km1 = km1;
		this.km2 = km2;
	}

	/**
	 * w = [wn wm] with wn - normal jump; wm: tangent jump. <br>
	 * On return, T = [Tn Tm]
	 */
	@Override
	public IVector getJumpTraction(Element e, int k) {
		int dim = e.getMeshPart().getDimension();
		IVector w = ((SDAElement) e).getCrackOpeningParameter();
		if (dim == 2) {
			double wn = w.get(0);
			double wm = w.get(1);
			double tn = ft * Math.exp(-wn / ef);
			double tm = km1 * wm;
			return new ArrayVector(tn, tm);
		} else if (dim == 3) {
			double wn = w.get(0);
			double wm1 = w.get(1);
			double wm2 = w.get(2);
			double tn = ft * Math.exp(-wn / ef);
			double tm1 = km1 * wm1;
			double tm2 = km2 * wm2;
			return new ArrayVector(tn, tm1, tm2);
		} else {
			throw new Error("invalid dimension");
		}
	}

	@Override
	public IMatrix getJumpStiffness(Element e, int k) {
		int dim = e.getMeshPart().getDimension();
		IVector w = ((SDAElement) e).getCrackOpeningParameter();
		if (dim == 2) {
			double wn = w.get(0);
			double tn = ft * Math.exp(-wn / ef);
			double[][] C = new double[][] { { -tn / ef, 0.0 }, { 0.0, km1 } };
			return new Array2DMatrix(C);
		} else if (dim == 3) {
			double wn = w.get(0);
			double tn = ft * Math.exp(-wn / ef);
			double[][] C = new double[][] { { -tn / ef, 0.0, 0.0 }, { 0.0, km1, 0.0 },
					{ 0.0, 0.0, km2 } };
			return new Array2DMatrix(C);
		} else {
			throw new Error("invalid dimension");
		}
	}

	@Override
	public void InitializeSolutionStep(Element e) {
	}

	@Override
	public void InitalizeNonlinearIteration(Element e) {
	}

	@Override
	public void FinalizeNonlinearIteration(Element e) {
	}

	@Override
	public void FinalizeSolutionStep(Element e) {
	}

	@Override
	public void CalculateOutputData(Element e) {
	}

}
